package test.factory;

import java.math.BigDecimal;

/**
 * 继续在简单工厂的例子的基础上进行改进
 * 还是算术运算(两个数字)
 * 好处：
 * 1.相对于简单工厂方法，这里使用了每个算法都有一个工厂去创建它，这样工厂类就不会职责那么重了
 * 2.假如我需要替换一个算法，只需要修改一行代码，就是创建工厂类的时候换另一个工厂
 * 3.完成了解耦合，假如我加法的算法类需要替换另一个类代替，只需要修改创建对应的加法工厂类就可以了
 * 缺点：
 * 1.每增加一个算法类都要创建一个工厂类，一个算法类，比起简单工厂模式，需要创建的类更多了
 * 2.客户端代码需要修改，假如我加法工厂类改名字了，我需要到各个客户端进行修改，大大增加了工作量，而且有可能出错，可维护性差
 * */
public class Factory {

    public static void main(String[] args) {
        // 客户端代码，首先创建一个工厂
        IFactory factory = new SubtractFactory();
        // 使用工厂创建相对应的算法
        Operation operation = factory.getOperationInstance();
        // 计算
        operation.setNumbers(new BigDecimal(1),new BigDecimal(2));
        System.out.print("结果："+operation.getResult());

    }

}



/**
 * 定义工厂父类
 * */
interface IFactory{

    Operation getOperationInstance();
}


/**
 * 定义加法运算的工厂类，实现IFactory接口
 * */
class AddFactory implements IFactory{

    @Override
    public Operation getOperationInstance() {
        return new Add();
    }
}

/**
 * 定义减法运算的工厂类，实现IFactory接口
 * */
class SubtractFactory implements IFactory{

    @Override
    public Operation getOperationInstance() {
        return new Subtract();
    }
}



/**
 * 定义运算的父类
 * */
abstract class Operation{

    // 数字A
    protected BigDecimal numberA;

    // 数字B
    protected BigDecimal numberB;

    // 设置数字
    public void setNumbers(BigDecimal numberA,BigDecimal numberB){
        this.numberA = numberA;
        this.numberB = numberB;
    }


    // 定义一个抽象方法，其子类必须实现此方法
    public abstract BigDecimal getResult();

}

/**
 * 定义运算的子类 +
 * */
class Add extends Operation {

    public BigDecimal getResult() {
        return numberA.add(numberB);
    }
}


/**
 * 定义运算的子类 -
 * */
class Subtract extends Operation {

    public BigDecimal getResult() {
        return numberA.subtract(numberB);
    }
}